package service

import (
	"context"
	"errors"
	"gin/webook/internal/domain"
	"gin/webook/internal/repository"
	"gin/webook/internal/web/validate"
	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

var (
	ErrDuplicateEmail        = repository.ErrDuplicateEmail
	ErrInvalidUserOrPassword = errors.New("用户名或密码不正确")
	ErrUserNotFound          = errors.New("用户不存在")
)

type UserService struct {
	repo *repository.UserRepository
}

func NewUserService(repo *repository.UserRepository) *UserService {
	return &UserService{repo: repo}
}

func (svc *UserService) SignUp(ctx context.Context, u domain.User) error {
	password, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(password)
	err = svc.repo.Create(ctx, u)
	if err == repository.ErrDuplicateEmail {
		return ErrDuplicateEmail
	}
	return err
}

func (svc *UserService) Login(ctx context.Context, email string, password string) (domain.User, error) {
	u, err := svc.repo.FindByEmail(ctx, email)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}
	//检查密码正确性
	err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	if err != nil {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	return u, nil
}

func (svc *UserService) GetUserInfo(ctx context.Context, uid int64) (domain.User, error) {
	u, err := svc.repo.FindByUid(ctx, uid)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrUserNotFound
	}
	if err != nil {
		return domain.User{}, err
	}

	return u, nil
}

func (svc *UserService) UpdateUserInfo(ctx *gin.Context, uid int64, req validate.ProfileReq) (domain.User, error) {
	//检测输入的参数
	err := validate.UpdateUserInfo(ctx, req)
	if err != nil {
		return domain.User{}, err
	}
	u, err := svc.repo.UpdateUserInfoByUid(ctx, uid, req)
	if err != nil {
		return domain.User{}, err
	}

	return u, nil
}
